/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package controladoresJPA;

import controladoresJPA.exceptions.IllegalOrphanException;
import controladoresJPA.exceptions.NonexistentEntityException;
import controladoresJPA.exceptions.PreexistingEntityException;
import entregapersistencia.*;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityNotFoundException;
import javax.persistence.Query;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;

/**
 *
 * @author dianacha
 */
public class FacturaJpaController implements Serializable {

    public FacturaJpaController(EntityManagerFactory emf) {
        this.emf = emf;
    }
    private EntityManagerFactory emf = null;

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    public void create(Factura factura) throws PreexistingEntityException, Exception {
        if (factura.getPagoCollection() == null) {
            factura.setPagoCollection(new ArrayList<Pago>());
        }
        if (factura.getProductoFacturaCollection() == null) {
            factura.setProductoFacturaCollection(new ArrayList<ProductoFactura>());
        }
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Usuario idUsuario = factura.getIdUsuario();
            if (idUsuario != null) {
                idUsuario = em.getReference(idUsuario.getClass(), idUsuario.getIdentificacion());
                factura.setIdUsuario(idUsuario);
            }
            Cliente cliente = factura.getCliente();
            if (cliente != null) {
                cliente = em.getReference(cliente.getClass(), cliente.getClientePK());
                factura.setCliente(cliente);
            }
            Collection<Pago> attachedPagoCollection = new ArrayList<Pago>();
            for (Pago pagoCollectionPagoToAttach : factura.getPagoCollection()) {
                pagoCollectionPagoToAttach = em.getReference(pagoCollectionPagoToAttach.getClass(), pagoCollectionPagoToAttach.getPagoPK());
                attachedPagoCollection.add(pagoCollectionPagoToAttach);
            }
            factura.setPagoCollection(attachedPagoCollection);
            Collection<ProductoFactura> attachedProductoFacturaCollection = new ArrayList<ProductoFactura>();
            for (ProductoFactura productoFacturaCollectionProductoFacturaToAttach : factura.getProductoFacturaCollection()) {
                productoFacturaCollectionProductoFacturaToAttach = em.getReference(productoFacturaCollectionProductoFacturaToAttach.getClass(), productoFacturaCollectionProductoFacturaToAttach.getProductoFacturaPK());
                attachedProductoFacturaCollection.add(productoFacturaCollectionProductoFacturaToAttach);
            }
            factura.setProductoFacturaCollection(attachedProductoFacturaCollection);
            em.persist(factura);
            if (idUsuario != null) {
                idUsuario.getFacturaCollection().add(factura);
                idUsuario = em.merge(idUsuario);
            }
            if (cliente != null) {
                cliente.getFacturaCollection().add(factura);
                cliente = em.merge(cliente);
            }
            for (Pago pagoCollectionPago : factura.getPagoCollection()) {
                Factura oldFacturaOfPagoCollectionPago = pagoCollectionPago.getFactura();
                pagoCollectionPago.setFactura(factura);
                pagoCollectionPago = em.merge(pagoCollectionPago);
                if (oldFacturaOfPagoCollectionPago != null) {
                    oldFacturaOfPagoCollectionPago.getPagoCollection().remove(pagoCollectionPago);
                    oldFacturaOfPagoCollectionPago = em.merge(oldFacturaOfPagoCollectionPago);
                }
            }
            for (ProductoFactura productoFacturaCollectionProductoFactura : factura.getProductoFacturaCollection()) {
                Factura oldFacturaOfProductoFacturaCollectionProductoFactura = productoFacturaCollectionProductoFactura.getFactura();
                productoFacturaCollectionProductoFactura.setFactura(factura);
                productoFacturaCollectionProductoFactura = em.merge(productoFacturaCollectionProductoFactura);
                if (oldFacturaOfProductoFacturaCollectionProductoFactura != null) {
                    oldFacturaOfProductoFacturaCollectionProductoFactura.getProductoFacturaCollection().remove(productoFacturaCollectionProductoFactura);
                    oldFacturaOfProductoFacturaCollectionProductoFactura = em.merge(oldFacturaOfProductoFacturaCollectionProductoFactura);
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            if (findFactura(factura.getId()) != null) {
                throw new PreexistingEntityException("Factura " + factura + " already exists.", ex);
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(Factura factura) throws IllegalOrphanException, NonexistentEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Factura persistentFactura = em.find(Factura.class, factura.getId());
            Usuario idUsuarioOld = persistentFactura.getIdUsuario();
            Usuario idUsuarioNew = factura.getIdUsuario();
            Cliente clienteOld = persistentFactura.getCliente();
            Cliente clienteNew = factura.getCliente();
            Collection<Pago> pagoCollectionOld = persistentFactura.getPagoCollection();
            Collection<Pago> pagoCollectionNew = factura.getPagoCollection();
            Collection<ProductoFactura> productoFacturaCollectionOld = persistentFactura.getProductoFacturaCollection();
            Collection<ProductoFactura> productoFacturaCollectionNew = factura.getProductoFacturaCollection();
            List<String> illegalOrphanMessages = null;
            for (Pago pagoCollectionOldPago : pagoCollectionOld) {
                if (!pagoCollectionNew.contains(pagoCollectionOldPago)) {
                    if (illegalOrphanMessages == null) {
                        illegalOrphanMessages = new ArrayList<String>();
                    }
                    illegalOrphanMessages.add("You must retain Pago " + pagoCollectionOldPago + " since its factura field is not nullable.");
                }
            }
            for (ProductoFactura productoFacturaCollectionOldProductoFactura : productoFacturaCollectionOld) {
                if (!productoFacturaCollectionNew.contains(productoFacturaCollectionOldProductoFactura)) {
                    if (illegalOrphanMessages == null) {
                        illegalOrphanMessages = new ArrayList<String>();
                    }
                    illegalOrphanMessages.add("You must retain ProductoFactura " + productoFacturaCollectionOldProductoFactura + " since its factura field is not nullable.");
                }
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            if (idUsuarioNew != null) {
                idUsuarioNew = em.getReference(idUsuarioNew.getClass(), idUsuarioNew.getIdentificacion());
                factura.setIdUsuario(idUsuarioNew);
            }
            if (clienteNew != null) {
                clienteNew = em.getReference(clienteNew.getClass(), clienteNew.getClientePK());
                factura.setCliente(clienteNew);
            }
            Collection<Pago> attachedPagoCollectionNew = new ArrayList<Pago>();
            for (Pago pagoCollectionNewPagoToAttach : pagoCollectionNew) {
                pagoCollectionNewPagoToAttach = em.getReference(pagoCollectionNewPagoToAttach.getClass(), pagoCollectionNewPagoToAttach.getPagoPK());
                attachedPagoCollectionNew.add(pagoCollectionNewPagoToAttach);
            }
            pagoCollectionNew = attachedPagoCollectionNew;
            factura.setPagoCollection(pagoCollectionNew);
            Collection<ProductoFactura> attachedProductoFacturaCollectionNew = new ArrayList<ProductoFactura>();
            for (ProductoFactura productoFacturaCollectionNewProductoFacturaToAttach : productoFacturaCollectionNew) {
                productoFacturaCollectionNewProductoFacturaToAttach = em.getReference(productoFacturaCollectionNewProductoFacturaToAttach.getClass(), productoFacturaCollectionNewProductoFacturaToAttach.getProductoFacturaPK());
                attachedProductoFacturaCollectionNew.add(productoFacturaCollectionNewProductoFacturaToAttach);
            }
            productoFacturaCollectionNew = attachedProductoFacturaCollectionNew;
            factura.setProductoFacturaCollection(productoFacturaCollectionNew);
            factura = em.merge(factura);
            if (idUsuarioOld != null && !idUsuarioOld.equals(idUsuarioNew)) {
                idUsuarioOld.getFacturaCollection().remove(factura);
                idUsuarioOld = em.merge(idUsuarioOld);
            }
            if (idUsuarioNew != null && !idUsuarioNew.equals(idUsuarioOld)) {
                idUsuarioNew.getFacturaCollection().add(factura);
                idUsuarioNew = em.merge(idUsuarioNew);
            }
            if (clienteOld != null && !clienteOld.equals(clienteNew)) {
                clienteOld.getFacturaCollection().remove(factura);
                clienteOld = em.merge(clienteOld);
            }
            if (clienteNew != null && !clienteNew.equals(clienteOld)) {
                clienteNew.getFacturaCollection().add(factura);
                clienteNew = em.merge(clienteNew);
            }
            for (Pago pagoCollectionNewPago : pagoCollectionNew) {
                if (!pagoCollectionOld.contains(pagoCollectionNewPago)) {
                    Factura oldFacturaOfPagoCollectionNewPago = pagoCollectionNewPago.getFactura();
                    pagoCollectionNewPago.setFactura(factura);
                    pagoCollectionNewPago = em.merge(pagoCollectionNewPago);
                    if (oldFacturaOfPagoCollectionNewPago != null && !oldFacturaOfPagoCollectionNewPago.equals(factura)) {
                        oldFacturaOfPagoCollectionNewPago.getPagoCollection().remove(pagoCollectionNewPago);
                        oldFacturaOfPagoCollectionNewPago = em.merge(oldFacturaOfPagoCollectionNewPago);
                    }
                }
            }
            for (ProductoFactura productoFacturaCollectionNewProductoFactura : productoFacturaCollectionNew) {
                if (!productoFacturaCollectionOld.contains(productoFacturaCollectionNewProductoFactura)) {
                    Factura oldFacturaOfProductoFacturaCollectionNewProductoFactura = productoFacturaCollectionNewProductoFactura.getFactura();
                    productoFacturaCollectionNewProductoFactura.setFactura(factura);
                    productoFacturaCollectionNewProductoFactura = em.merge(productoFacturaCollectionNewProductoFactura);
                    if (oldFacturaOfProductoFacturaCollectionNewProductoFactura != null && !oldFacturaOfProductoFacturaCollectionNewProductoFactura.equals(factura)) {
                        oldFacturaOfProductoFacturaCollectionNewProductoFactura.getProductoFacturaCollection().remove(productoFacturaCollectionNewProductoFactura);
                        oldFacturaOfProductoFacturaCollectionNewProductoFactura = em.merge(oldFacturaOfProductoFacturaCollectionNewProductoFactura);
                    }
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                String id = factura.getId();
                if (findFactura(id) == null) {
                    throw new NonexistentEntityException("The factura with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(String id) throws IllegalOrphanException, NonexistentEntityException {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Factura factura;
            try {
                factura = em.getReference(Factura.class, id);
                factura.getId();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The factura with id " + id + " no longer exists.", enfe);
            }
            List<String> illegalOrphanMessages = null;
            Collection<Pago> pagoCollectionOrphanCheck = factura.getPagoCollection();
            for (Pago pagoCollectionOrphanCheckPago : pagoCollectionOrphanCheck) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Factura (" + factura + ") cannot be destroyed since the Pago " + pagoCollectionOrphanCheckPago + " in its pagoCollection field has a non-nullable factura field.");
            }
            Collection<ProductoFactura> productoFacturaCollectionOrphanCheck = factura.getProductoFacturaCollection();
            for (ProductoFactura productoFacturaCollectionOrphanCheckProductoFactura : productoFacturaCollectionOrphanCheck) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Factura (" + factura + ") cannot be destroyed since the ProductoFactura " + productoFacturaCollectionOrphanCheckProductoFactura + " in its productoFacturaCollection field has a non-nullable factura field.");
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            Usuario idUsuario = factura.getIdUsuario();
            if (idUsuario != null) {
                idUsuario.getFacturaCollection().remove(factura);
                idUsuario = em.merge(idUsuario);
            }
            Cliente cliente = factura.getCliente();
            if (cliente != null) {
                cliente.getFacturaCollection().remove(factura);
                cliente = em.merge(cliente);
            }
            em.remove(factura);
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public List<Factura> findFacturaEntities() {
        return findFacturaEntities(true, -1, -1);
    }

    public List<Factura> findFacturaEntities(int maxResults, int firstResult) {
        return findFacturaEntities(false, maxResults, firstResult);
    }

    private List<Factura> findFacturaEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            cq.select(cq.from(Factura.class));
            Query q = em.createQuery(cq);
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public Factura findFactura(String id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Factura.class, id);
        } finally {
            em.close();
        }
    }

    public int getFacturaCount() {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            Root<Factura> rt = cq.from(Factura.class);
            cq.select(em.getCriteriaBuilder().count(rt));
            Query q = em.createQuery(cq);
            return ((Long) q.getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }
    
}
